package com.bsm.jam.shiro;

import com.bsm.jam.constant.Global;
import com.bsm.jam.constant.Setting;
import com.bsm.jam.sys.entity.SysRole;
import com.bsm.jam.sys.entity.SysUser;
import com.bsm.jam.sys.service.ISysRoleService;
import com.bsm.jam.sys.service.ISysUserService;
import com.bsm.jam.utils.Encodes;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 *
 * 自定义权限认证
 * @author baijun
 * @date 2018-4-16 15:04:04
 */
@Component(value = "authRealm")
public class AuthRealm extends AuthorizingRealm{

    /** 日志 */
    private static Logger logger= LoggerFactory.getLogger(AuthRealm.class);

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ISysRoleService sysRoleService;
    /**
     * 设定密码校验的Hash算法与迭代次数
     */
    @PostConstruct
    public void initCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(Setting.HASH_ALGORITHM);
        matcher.setHashIterations(Setting.HASH_INTERATIONS);
        setCredentialsMatcher(matcher);
        logger.info("---------密码校验器  -matcher----------------");
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info("登录授权");
        ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        for (SysRole sysRole : sysRoleService.selectRoleByUserId(shiroUser.getId())) {
            // 基于Role的权限信息
            info.addRole(sysRole.getCode());
            // 基于Permission的权限信息
            info.addStringPermissions(sysRole.getPermissionList());
        }
        return info;
    }

    /**
     * 认证回调函数,登录时调用.
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName = ((UsernamePasswordToken)token).getUsername();
        SysUser sysUser = sysUserService.getByLoginName(userName);
        try {
            if (sysUser != null) {
                logger.info(sysUser.getName()+"登录");
                if (Global.NO.equals(sysUser.getLoginFlag())) {
                    throw new DisabledAccountException();
                }
                byte[] salt = Encodes.decodeHex(sysUser.getPassword().substring(0, 16));
                return new SimpleAuthenticationInfo(new ShiroUser(sysUser.getId(),userName, sysUser.getName()),
                        sysUser.getPassword().substring(16), ByteSource.Util.bytes(salt),
                        getName());
            } else {
                logger.info(sysUser.getName()+"登录失败");
                throw new AuthenticationException();
            }
        } catch (NullPointerException e) {
            throw new UnknownAccountException();
        }
    }
}
